﻿#ifndef  RX_WORLD_H
#define RX_WORLD_H

#include <memory>

#include <metainfo.h>
#include <threadsafe.h>
#include "RXECSDef.h"
#include <RXEntitySystem_global.h>


class RXNode;
class RXEntity;

class RXWorldEventListenr {
public:
	virtual void RXWorldEventListener() {};
	virtual void NodeSpawned(RXNode* node,bool isRoot) = 0;
	virtual void NodeDeleted(RXECSDef::NodeId id) = 0;
	virtual void NodePropertyChanged(RXECSDef::NodeId id, int PropertyId, Variant value) = 0;
	virtual void NodeEventToShadow(RXECSDef::NodeId id,ThreadSafe::Event* e) = 0;
};

typedef std::shared_ptr<RXWorldEventListenr> RXWorldEventListenrPtr;
typedef std::vector<RXWorldEventListenrPtr> RXWorldEventListenrList;

//用于存放和管理RXNode的对象，当World析构时，内部节点自动析构。World有一个根节点，伴随World的创建而出现，不可被人为外部析构。
//当服务端使用公有创建时，客户端会对应的创建对象。如果该对象有内部组件（即在构造函数内创建的组件），则组件必须有稳定的命名（名字在该实体内不可重复）用于网络同步系统
class RXEntitySystem_EXPORT RXWorld {

public:
	RXWorld();
	~RXWorld();

public:
	void AddWorldListener(RXWorldEventListenrPtr e);;
	void RemoveWorldListener(RXWorldEventListenrPtr e);
public:
	//当RXWorld被引擎（AspectEngine)推动时，WorldTime代表当前世界所在的帧时间，WorldTimeDelta代表当前帧时间与上次帧时间的差值

	//获取世界帧时间
	std::chrono::system_clock GetWorldTime();

	//获取世界时间片大小
	std::chrono::milliseconds GetWorldTimeDelta();

public:
	//加载插件类库,将里面的RXNode的子类类型提取出来
	bool LoadLibrary(const char* lib);

	template <typename T>
	T* Spawn(RXEntity* parent) {
		return dynamic_cast<T*>(SpawnImp(T::staticMetaInfo(),parent));
	}
	
	//生成节点
	RXNode* Spawn(const char* className, RXEntity* parent);

	template<typename T>
	void RegisterClass() {
		RegisterClassImp(T::staticMetaInfo(), T::staticMetaInfo().ClassName());
	}

	template<typename T>
	void RegisterClass(const char* name) {
		RegisterClassImp(T::staticMetaInfo(),name);
	}

	void RegisterClass(const MetaInfo& info);

	//获取根节点
	RXEntity* GetRootEntity();

	//设置根节点。如果之前有存在根节点，则之前的根节点会被析构
	void SetRootEntity(RXEntity* root);

	//通过id寻找Node
	RXNode* GetNode(RXECSDef::NodeId id);

private:
	void RegisterNode(RXNode* node);
	void UnRegisterNode(RXNode* node);
	RXECSDef::NodeId AllocNodeId();//申请节点ID
private:
	RXNode* SpawnImp(const MetaInfo& m, RXEntity* parent);
	void RegisterClassImp(const MetaInfo& m,const char* className);
	void PostEventToShadowNode(RXNode* target,ThreadSafe::Event* event);//向后端节点发送事件
private:
	struct Private;
	std::unique_ptr<Private> _P;
	friend class RXNode;

};

#endif // ! RX_WORLD_H
